#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <ESP8266WiFi.h>
#include "main.h"
#include "wifis.h"
#include "assitant.h"
const char *AP_NAME = "ESP8266";
DNSServer *dnsServer;
ESP8266WebServer *server = NULL;
bool _sap_is_on = false;

int sap_start(int n, char *args[]);
int sap_loop();
int sap_stop(int n, char *args[]);
int sap_status(int n, char *args[]);
int cmd_smart_config(int n, char *args[]);
void handleRoot();
void handleConfigWifi();

void sap_init()
{
    public_a_cmd_link("sap", cmd_smart_config);
}
int sap_start(int n, char *args[])
{
    assert_msg(!_sap_is_on, "sap service is already on, use 'sap stop'");
    assert_msg(n > 1, "usage: start ip [ssid] [psw]");
    String _ips(args[1]);
    int _f = 0;
    byte octet[4];
    for (int i = 0; i < 3; i++)
    {
        int ind = _ips.indexOf('.', _f);
        assert_msg(ind > 0, "invalid ip address");
        octet[i] = _ips.substring(_f, ind).toInt();
        _f = ind + 1;
    }
    octet[3] = _ips.substring(_f).toInt();
    IPAddress apIP(octet[0], octet[1], octet[2], octet[3]);
    dnsServer = new DNSServer();
    server = new ESP8266WebServer();
    _sap_is_on = true;
    WiFi.mode(WIFI_AP_STA);
    WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
    const char *ap_name = n > 2 ? args[2] : AP_NAME;
    const char *psk = n > 3 ? args[3] : NULL;
    WiFi.softAP(ap_name, psk);
    server->on("/", HTTP_GET, handleRoot);
    server->onNotFound(handleRoot);
    server->on("/cnt", HTTP_GET, handleConfigWifi);
    server->begin();
    dnsServer->start(53, "*", apIP);
    if (!had_timer(sap_loop))
    {
        public_a_timer(sap_loop, Hz(13));
    }
    return 0;
}

int sap_loop()
{
    server->handleClient();
    dnsServer->processNextRequest();
    return 0;
}

int sap_stop(int n, char *args[])
{
    assert_msg(_sap_is_on, "sap service not started");
    remove_a_timer(sap_loop);
    WiFi.softAPdisconnect();
    server->stop();
    dnsServer->stop();
    delete dnsServer;
    delete server;
    _sap_is_on = false;
    WiFi.mode(WIFI_STA);
    return 0;
}

int sap_status(int n, char *args[])
{
    if (!_sap_is_on)
    {
        lily_out("sap service is off\n");
        return 0;
    }
    char tx[64];
    sprintf(tx, "AP ssid:%s\n psk:%s\n", WiFi.softAPSSID().c_str(), WiFi.softAPPSK().c_str());
    lily_out(tx);
    sprintf(tx, "AP ip:%s\nMAC:%s\n", WiFi.softAPIP().toString().c_str(), WiFi.softAPmacAddress().c_str());
    lily_out(tx);
    n = WiFi.softAPgetStationNum();
    sprintf(tx, "%d connected\n", n);
    lily_out(tx);
    return 0;
}

int cmd_smart_config(int n, char *args[])
{
    const char *er_msg = "to start a softAP service\nusage: sap start [ssid] [pwd]\n sap stop\n sap status";
    assert_msg(n > 1, er_msg);
    if (strcmp(args[1], "start") == 0)
    {
        return sap_start(n - 1, args + 1);
    }

    if (strcmp(args[1], "stop") == 0)
    {
        return sap_stop(n - 1, args + 1);
    }
    if (strcmp(args[1], "status") == 0)
    {
        return sap_status(n - 1, args + 1);
    }
    return 0;
}

int _fetch_cnt = 0;
void handleRoot()
{
#include "smartPAP_page.h"
    server->send(200, "text/html", page_html);
    _fetch_cnt = 1;
}

void handleConfigWifi()
{
    if (!_sap_is_on)
        return;
    xout_("c:");
    xouts(server->arg("c"));
    var cnt = server->arg("c").toInt();
    if (cnt < _fetch_cnt)
    {
        xouts(cnt);
        return;
    }
    var in_stop = stop_schedule();
    _fetch_cnt += cnt + 1;
    char *base64_decode(const char *code);
    char *ssid = base64_decode(server->arg("ssid").c_str());
    char *psk = base64_decode(server->arg("pwd").c_str());

    xout_("ssid:");
    xouts(ssid);
    xout_("psk:");
    xouts(psk);

    if (WiFi.isConnected())
    {
        WiFi.disconnect();
    }
    int ok = wifi_connect(ssid, psk);
    delete ssid;
    delete psk;
    if (ok)
    {
        server->send(200, "text/plain", "连接成功，请关闭此网页");
        // sap_stop(0, NULL);
        create_or_change_quick_timer_count([]()
                                           { sap_stop(0, NULL); return 0 ; },
                                           Second(3));
    }
    else
        server->send(200, "text/plain", "连接失败");
    if (in_stop)
        resume_schedule();
}
// sap start 192.168.2.1 esp8266 ********